﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using TSharp.Core.Env;

namespace TSharp.Core.Security
{
    /// <summary>
    ///     提供用于计算指定文件哈希值的方法
    ///     <example>
    ///         例如计算文件的MD5值:
    ///         <code>
    /// String hashMd5=HashHelper.ComputeMD5("MyFile.txt");
    /// </code>
    ///     </example>
    ///     <example>
    ///         例如计算文件的CRC32值:
    ///         <code>
    /// String hashCrc32 = HashHelper.ComputeCRC32("MyFile.txt");
    /// </code>
    ///     </example>
    ///     <example>
    ///         例如计算文件的SHA1值:
    ///         <code>
    /// String hashSha1 =HashHelper.ComputeSHA1("MyFile.txt");
    /// </code>
    ///     </example>
    /// </summary>
    public sealed class HashHelper
    {
        /// <summary>
        ///     计算字符串Md5
        /// </summary>
        /// <param name="source">密码</param>
        /// <returns>加密字符串</returns>
        public static string StringMd5(string source)
        {
            byte[] pwdBytes = TSharpGlobal.Encoding.GetBytes(source);
            MD5 md5 = MD5.Create();
            byte[] encryptedBytes = md5.ComputeHash(pwdBytes);
            var stringBuilder = new StringBuilder(32);
            for (int i = 0; i < encryptedBytes.Length; i++)
            {
                stringBuilder.Append(encryptedBytes[i].ToString("x2"));
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        ///     计算指定文件的MD5值
        /// </summary>
        /// <param name="fileName">指定文件的完全限定名称</param>
        /// <returns>返回值的字符串形式</returns>
        public static String FileMd5(String fileName)
        {
            var hashMd5 = String.Empty;
            //检查文件是否存在，如果文件存在则进行计算，否则返回空值
            if (File.Exists(fileName))
            {
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    //计算文件的MD5值
                    MD5 calculator = MD5.Create();
                    Byte[] buffer = calculator.ComputeHash(fs);
                    calculator.Clear();
                    //将字节数组转换成十六进制的字符串形式
                    var stringBuilder = new StringBuilder(32);
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        stringBuilder.Append(buffer[i].ToString("x2"));
                    }
                    hashMd5 = stringBuilder.ToString();
                } //关闭文件流
            } //结束计算
            return hashMd5;
        }

        //ComputeMD5
        /// <summary>
        ///     计算指定文件的CRC32值
        /// </summary>
        /// <param name="fileName">指定文件的完全限定名称</param>
        /// <returns>返回值的字符串形式</returns>
        public static String FileCrc32(String fileName)
        {
            var hashCrc32 = String.Empty;
            //检查文件是否存在，如果文件存在则进行计算，否则返回空值
            if (File.Exists(fileName))
            {
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    //计算文件的CSC32值
                    var calculator = new Crc32();
                    Byte[] buffer = calculator.ComputeHash(fs);
                    calculator.Clear();
                    //将字节数组转换成十六进制的字符串形式
                    var stringBuilder = new StringBuilder();
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        stringBuilder.Append(buffer[i].ToString("x2"));
                    }
                    hashCrc32 = stringBuilder.ToString();
                } //关闭文件流
            }
            return hashCrc32;
        }
        /// <summary>
        ///     计算指定文件的CRC32值
        /// </summary>
        /// <param name="source">指定文件的完全限定名称</param>
        /// <returns>返回值的字符串形式</returns>
        public static String StringCrc32(String source)
        {
            var sourceBytes = TSharpGlobal.Encoding.GetBytes(source);

            //计算文件的CSC32值
            var calculator = new Crc32();
            Byte[] buffer = calculator.ComputeHash(sourceBytes);
            calculator.Clear();
            //将字节数组转换成十六进制的字符串形式
            var stringBuilder = new StringBuilder(32);
            for (int i = 0; i < buffer.Length; i++)
            {
                stringBuilder.Append(buffer[i].ToString("x2"));
            }
            var hashCrc32 = stringBuilder.ToString();
            return hashCrc32;
        }
        //ComputeCRC32
        /// <summary>
        ///     计算指定文件的SHA1值
        /// </summary>
        /// <param name="fileName">指定文件的完全限定名称</param>
        /// <returns>返回值的字符串形式</returns>
        public static String FileSha1(String fileName)
        {
            var hashSha1 = String.Empty;
            //检查文件是否存在，如果文件存在则进行计算，否则返回空值
            if (File.Exists(fileName))
            {
                using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    //计算文件的SHA1值
                    SHA1 calculator = SHA1.Create();
                    Byte[] buffer = calculator.ComputeHash(fs);
                    calculator.Clear();
                    //将字节数组转换成十六进制的字符串形式
                    var stringBuilder = new StringBuilder();
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        stringBuilder.Append(buffer[i].ToString("x2"));
                    }
                    hashSha1 = stringBuilder.ToString();
                } //关闭文件流
            }
            return hashSha1;
        }
        /// <summary>
        /// 计算指定字符串的SHA1值
        /// </summary>
        /// <param name="source">Name of the file.</param>
        /// <returns>String.</returns>
        public static String StringSha1(String source)
        {
            //检查文件是否存在，如果文件存在则进行计算，否则返回空值
            var sourceBytes = TSharpGlobal.Encoding.GetBytes(source);

            //计算文件的SHA1值
            SHA1 calculator = SHA1.Create();
            Byte[] buffer = calculator.ComputeHash(sourceBytes);
            calculator.Clear();
            //将字节数组转换成十六进制的字符串形式
            var stringBuilder = new StringBuilder(32);
            for (int i = 0; i < buffer.Length; i++)
            {
                stringBuilder.Append(buffer[i].ToString("x2"));
            }
            return stringBuilder.ToString();
        }
    }
}